package com.sgl.retrofitdemo.net;

import android.os.Build;
import android.text.TextUtils;

import com.sgl.retrofitdemo.RetrofitApplication;
import com.sgl.retrofitdemo.utils.RetrofitConst;
import com.sgl.retrofitdemo.utils.SafetyUtil;
import com.sgl.retrofitdemo.utils.SharedPrefUtil;
import com.sgl.retrofitdemo.utils.StringUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by sunqiyong on 2016/11/13.
 * 公共拦截器，增加网络通用参数
 */

public class PublicInterceptor implements Interceptor{
    private static final String PREKEY = "253248d67598bde422bad0345354134e";
    private static final String SESSION_CODE_KEY = "session_code";
    private static final String LINKER = "=";
    private static final String UDID = "udid";
    private static ArrayList<String> exclude;

    static {
        // 'client_secret','debug','class_name','method_name','project','version'
        // 不参与加密、解密
        exclude = new ArrayList<String>();
        exclude.add("client_secret");
        exclude.add("debug");
        exclude.add("class_name");
        exclude.add("method_name");
        exclude.add("project");
        exclude.add("version");
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originRequest = chain.request();
        HttpUrl.Builder builder = originRequest.url().newBuilder();
        builder.setQueryParameter("debug", "Y2016");
        /**
         * 增加公共参数
         *
         * |client_secret|string|接口传参的签名|是|无|MD5|
         * |app_version|float|版本|是|无|1.0|
         * |v|int|接口版本|是|无|1|
         * |os_version|string|系统版本+机器型号|是|无|Android4.4:mi|
         * |client_type|string|手机型号|是|无|iphone/android/ipad|
         * |screen_size|string|手机尺寸|是|无|800x900|
         * |session_code|string|用户登录会话Code|否|无|abcd123|
         * |city_id|int|当前定位城市id|否|无|10|
         * |longitude|float|当前位置经度|否|0.0|143.102230|
         * |latitude|float|当前位置纬度|否|0.0|120.123320|
         * |debug|string|是否Debug对所有校验有效|否|N|N/Y|
         * |mapto|string|目标经纬度类型|否|N|baidu|
         * |mapfrom|string|原来经纬度类型|否|gps|
         * |lang|string|当前使用语言|否|zh|
         */
        // 每个接口需要增加 v=? 的参数
        try {
            List<String> paths = originRequest.url().pathSegments();
            if (null != paths && paths.size() > 0) {
                for (String path : paths) {
                    if (null != path && path.startsWith("v")) {
                        if (path.matches("^v[0-9]{1,}$")) {
                            builder.setQueryParameter("v", path.substring(1));
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        builder.setQueryParameter("app_version", "1.6");
        builder.setQueryParameter("client_type", "android");
        builder.setQueryParameter("os_version", "Android" + Build.VERSION.RELEASE + ":" + android.os.Build.MODEL);
        builder.setQueryParameter("screen_size", RetrofitApplication.SCREEN_H + "*" + RetrofitApplication.SCREEN_W);
        String session = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                getString(RetrofitConst.SHARED_PREF_KEY_SESSION_CODE, "");
        if (null != session && session.trim().length() > 0) {
            builder.setQueryParameter("session_code", session);
        }
        double locationLat = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                getFloat(RetrofitConst.SHARED_PREF_KEY_LOCATION_LAT, 0);
        double locationLon = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                getFloat(RetrofitConst.SHARED_PREF_KEY_LOCATION_LON, 0);
        if (locationLat > 0 && locationLon > 0) {
            builder.setQueryParameter("longitude", String.valueOf(locationLon));
            builder.setQueryParameter("latitude", String.valueOf(locationLat));
        }
        String cityid = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                getString(RetrofitConst.SHARED_PREF_KEY_CURRENT_CITY_ID, "");

        // change by Castiel 16.08.17
        // 先判断参数内是否有city_id
        boolean paramsNotExistsCityID = StringUtil.isEmpty(originRequest.url().queryParameter("city_id"));
        if (paramsNotExistsCityID && null != cityid && cityid.trim().length() > 0) {
            builder.setQueryParameter("city_id", cityid);
        }

        builder.setQueryParameter("private_key", PREKEY);
        HttpUrl publicQueryParamsUrl = builder.build();
        HttpUrl resulstUrl = setSecretParams(publicQueryParamsUrl);
        return chain.proceed(originRequest.newBuilder().
                url(resulstUrl).
                method(originRequest.method(), originRequest.body()).
                header("User-Agent", "YohoMars").build());
    }

    /**
     * 参数加密
     * <h>'client_secret','debug','class_name','method_name','project','version'</>
     * 不参与加密
     *
     * @param httpUrl
     * @return
     */
    private HttpUrl setSecretParams(HttpUrl httpUrl) {
        HttpUrl.Builder builder = httpUrl.newBuilder();
        HashMap<String, String> param = new HashMap<String, String>();
        // FIXME: 更加完善的遍历方法
        for (int i = 0; i < httpUrl.querySize(); i++) {
            String name = httpUrl.queryParameterName(i);
            String value = httpUrl.queryParameterValue(i);
            // 不参与加密的字段
            if (!exclude.contains(name)) {
                param.put(name, value);
            }
        }
        String client_secret = SafetyUtil.encryptStringToMd5(transMapToString(param), "32");
        builder.removeAllQueryParameters("private_key");
        return builder.addQueryParameter("client_secret", client_secret).build();
    }

    /**
     * 参数排序
     *
     * @param params
     * @return
     */
    public static String transMapToString(Map<String, String> params) {
        Map.Entry<String, String> entry;
        StringBuffer sb = new StringBuffer();
        TreeMap<String, String> treeMap = new TreeMap<String, String>(
                new Comparator<String>() {
                    @Override
                    public int compare(String lhs, String rhs) {
                        return lhs.compareTo(rhs);
                    }
                });
        treeMap.putAll(params);
        for (Iterator<Map.Entry<String, String>> iterator = treeMap.entrySet()
                .iterator(); iterator.hasNext(); ) {
            entry = (Map.Entry<String, String>) iterator.next();
            sb.append(entry.getKey().trim())
                    .append("=")
                    .append(null == entry.getValue() ? "" : entry.getValue().trim())
                    .append(iterator.hasNext() ? "&" : "");
        }
        String parameters = sb.toString();
        // parameters = parameters.replaceAll(" ", "");
        parameters = parameters.replaceAll("\n", "");
        parameters = parameters.replaceAll("\r", "");
        parameters = parameters.replaceAll("\t", "");
        return parameters;
    }

    public static String setSecretParams(String url) {
        String resultUrl = url;
        if (!TextUtils.isEmpty(url)) {
            StringBuffer sb = new StringBuffer(url);
            String session = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                    getString(RetrofitConst.SHARED_PREF_KEY_SESSION_CODE, "");
            String uid = SharedPrefUtil.instance(RetrofitApplication.getInstance()).
                    getString(RetrofitConst.SHARED_PREF_KEY_UID, "");

            if (!url.contains("?")) {
                sb.append("?");
            } else {
                sb.append("&");
            }
            if (null != session && session.trim().length() > 0) {
                sb.append(SESSION_CODE_KEY).append(LINKER).append(session).append("&");
            }
            sb.append(UDID).append(LINKER).append(RetrofitApplication.UDID).append("&");
            sb.append("uid").append(LINKER).append(uid);
            resultUrl = sb.toString();
        }
        return resultUrl;
    }


}
